#pragma once

#include "../dispatcher.h"
#include "../server.h"


namespace evm { namespace messaging {

/* A message dispatcher which understands RPC messages.
 *
 * A MessageHandlingServer is constructed by passing a callable dispatcher
 * which is invoked with message dictionaries each time a message
 * is received.
 *
 * RPCDispatcher is one such dispatcher which understands the format of RPC
 * messages. The dispatcher looks at the namespace and method values
 * in the message and matches those against a list of available endpoints.
 *
 * Endpoints may have a target attribute describing the namespace of the
 * methods exposed by that object. All public methods on an endpoint
 * object are remotely invokable by clients.
 */
struct RPCDispatcher : BaseDispatcher {
    RPCDispatcher(TargetPtr target, Endpoints endpoints)
        : BaseDispatcher(endpoints), target(target) {}

    ListenerPtr listen(TransportPtr transport) override {
        return transport->listen(target);
    }

    void operator()(IncomingMsgPtr incoming) override;

private:
    Json dispatch(const Json& message);

    /* Listening target. */
    TargetPtr target;

    /* Default target with null namespace, for endpoints which have no target. */
    TargetPtr default_target = make_shared<Target>();
};

MessageServerPtr get_rpc_server(TransportPtr transport,
                                TargetPtr target, Endpoints endpoints);

}}
